package cn.ichiva.dl.tushare.analy;

import cn.ichiva.dl.tushare.analy.impl.Statistical;
import cn.ichiva.dl.tushare.analy.impl.TradeAgent;
import cn.ichiva.dl.tushare.analy.impl.TradeAgentList;
import cn.ichiva.dl.tushare.common.ScoreAgent;
import cn.ichiva.common.concurrent.*;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 第二阶段环境
 *
 * 股票 & 利率环境
 */
@Slf4j
public class TradeAgentEvn {

    private AgentList list;

    /**
     * AI 排行榜
     */
    public TradeAgentEvn(List<TradeAgent> initAgent){
        init(initAgent);
    }

    /**
     * 随机排序初始化ai
     *
     * @param initAgent
     */
    private void init(List<TradeAgent> initAgent) {
        list = new TradeAgentList(initAgent);
        log.info("构建环境成功");
    }

    public TradeAgentEvn() {
        List<TradeAgent> initAgent = new ArrayList<>();
        for (int i = 0; i < 8; i++) {
            initAgent.add(new TradeAgent(AgentConfig2442.getInstance()));
        }
        init(initAgent);
    }

    ArrayBlockingQueue<TradeAgent> queue = new ArrayBlockingQueue<>(16);


    /**
     * 进化
     * @param number 次数
     * @param nThread 线程数
     * @throws InterruptedException
     */
    public void evolution(int number,int nThread) throws InterruptedException {
        ThreadPoolExecutor executor = ExecutorsPlus.newBlockFixedThreadPool(nThread);
        log.info("start...");
        for (int i = 0; i < nThread; i++) {
            executor.submit(() ->{
                    while (!Thread.currentThread().isInterrupted()){
                        TradeAgent agent = queue.poll();
                        try{
                            if(agent != null) contend(agent);
                            else Thread.sleep(1000);
                        }catch (Throwable e){
                            e.printStackTrace();
                        }
                    }

            });
        }

        long time = System.currentTimeMillis();
        for (int i = 0; i < number; i++) {
            queue.put((TradeAgent) list.getNewAgent());
            if (i % 1000 == 0) {
                long t0 = System.currentTimeMillis();
                log.info("1000 agent time = {}s", (t0 - time) / 1000);
                time = t0;
            }
        }
        log.info("end...");
    }

    /**
     * 竞争
     * @param agent
     */
    public void contend(TradeAgent agent) {
        if (TrainHelper.contend(agent)) {
            ScoreAgent scoreAgent = this.list.put(agent);
            if(scoreAgent != null){
                Statistical.writeAgent(agent);
                log.info("进入排行榜 {}",agent);
            }
        }
    }
}
